package com.gzx.spring.drools.service;

import com.alibaba.excel.util.DateUtils;
import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.gzx.risk.core.apis.context.ApiContext;
import com.gzx.risk.core.enums.AuthStatus;
import com.gzx.risk.core.enums.RiskNodes;
import com.gzx.risk.core.pojo.*;
import com.gzx.risk.core.service.*;
import com.gzx.risk.core.utils.WechatBotKeyEnum;
import com.gzx.risk.core.utils.WechatNotificationType;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.Period;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class RiskWorkService {
	@Resource
	private RiskService riskService;
	@Resource
	private DroolsService droolsService;
	@Resource
	private OrderOpService orderOpService;
	@Resource
	private WeChatService weChatService;
    @Resource
    private CreditService creditService;
    @Resource
    private OrderInfoService orderInfoService;
    @Resource
    private ILockControlService lockControlService;

	public void exec() {
		for (OrderInfo order : riskService.findRiskOrders()) {
			long gap = System.currentTimeMillis() - order.getCreatetime() * 1000;
			if (gap >= TimeUnit.HOURS.toMillis(1)) {
				String createTime = DateUtils.format(new Date(order.getCreatetime() * 1000), "");
				log.info("风控一阶段执行 超过4小时订单 ordercode:{},createTime:{}", order.getOrdercode(), createTime);
				log.info("风控一阶段执行 开始 ordercode:{}", order.getOrdercode());
				execOrder(order);
				log.info("风控一阶段执行 结束 ordercode:{}", order.getOrdercode());
			} else {
				log.info("风控一阶段执行 未到4小时订单 ordercode:{}", order.getOrdercode());
			}
		}
	}

	public Boolean exec(int oid) {
		return execOrder(riskService.findRiskOrder(oid));
	}

	private Boolean execOrder(OrderInfo order) {
        String orderCode = order.getOrdercode();
        String debounceKey = "risk:debounce:" + orderCode;

        if (!lockControlService.tryDebounce(debounceKey, 30, TimeUnit.SECONDS)) {
            log.info("风控防抖命中，跳过执行 ordercode: {}", orderCode);
            return true; // 视为已处理（和 isInRisk 逻辑一致）
        }

		String createTime = DateUtils.format(new Date(order.getCreatetime() * 1000), "yyyyMMdd");
		String endTime = DateUtils.format(new Date(order.getCreatetime() * 1000 + TimeUnit.DAYS.toMillis(100)), "yyyyMMdd");
		if (riskService.isInRisk(order.getOrdercode())) {
			log.info("风控一阶段执行 ordercode:{},createTime:{} 已在信审中", order.getOrdercode(), createTime);
			// 说明已经通过风控
			return true;
		}
		log.info("风控一阶段执行 ordercode:{},createTime:{}", order.getOrdercode(), createTime);
		try {
			UserInfo userInfo = riskService.findUserInfo(order.getUid());

            if (userInfo == null) {
				log.info("NotFound User ordercode:{},createTime:{}", order.getOrdercode(), createTime);
				reject(order);
				return false;
			}

            CreditFile creditFile = orderInfoService.getContractInfo(order.getOrdercode());
            if (creditFile == null) {
                log.info("User creditFile is null, orderCode:{},createTime:{}", order.getOrdercode(), createTime);
                return false;
            }

            userInfo = this.buildFullUserInfo(userInfo,creditFile);


			// 白名单，直接返回
			if (riskService.isWhite(userInfo.getId())) {
				ApiContext ctx = this.initApiContext(order, userInfo);
				ctx.setRejectMsg("命中白名单");
				log.info("风控一阶段执行 ordercode:{},createTime:{},命中白名单，风控跳过", order.getOrdercode(), createTime);
				riskService.log(ctx);
				creditReview(order, ctx);
				return true;
			}

			RiskRuleResultInfo resultInfo = riskService.findLastRiskRuleResult(userInfo.getId());

			// 最近一次为拒绝，小于30天
			if (resultInfo != null && "false".equals(resultInfo.getRuleResult())) {
				String lastResultTime = DateUtils.format(resultInfo.getCreatedTime(), DateUtils.DATE_FORMAT_14);
				log.info("风控一阶段执行 name:{},id:{},lastResultTime:{}", userInfo.getName(), userInfo.getId(), lastResultTime);
				LocalDate currentDate = LocalDate.now();
				Period period = Period.between(resultInfo.getCreatedTime().toLocalDate(), currentDate);
				if (period.getDays() < 30) {
					log.info("风控一阶段执行 resultInfo.id:{},ordercode:{},createTime:{}，30天内已被拒绝，风控失败",
                            resultInfo.getId(), order.getOrdercode(), createTime);
					reject(order);
					return false;
				}
			}

			ApiContext ctx = this.initApiContext(order, userInfo);
			ctx.setAuthDate(createTime + "-" + endTime);// 20250804-20250830
			log.info("风控一阶段执行 name:{},id:{},lastDate:{},authDate:{}", userInfo.getName(), userInfo.getId(),
					userInfo.getIdLastdate(), ctx.getAuthDate());

			if (riskService.isBlack(userInfo.getId())) {
				log.info("风控一阶段执行 ordercode:{},createTime:{},命中黑名单，风控失败", order.getOrdercode(), createTime);
				reject(order);
				return false;
			}

            if (Objects.equals(AuthStatus.AUTH_FAILED.getCode(), ctx.getUserInfo().getCreditAuthInfo().getAuthorizationStatus())){
                log.info("风控一阶段执行 该用户征信授权失败 name:{},id_card:{},ordercode:{},createTime:{}",
                        ctx.getUserInfo().getName(),ctx.getUserInfo().getId(),order.getOrdercode(),createTime);
                reject(order);
                return false;
            }

            droolsService.exec(ctx); // 执行风控规则

			if (ctx.getRuleResult() != null && ctx.getRuleResult()) {
				log.info("风控执行 ordercode:{},createTime:{},风控一阶段成功,yushou期数:{}", order.getOrdercode(), createTime,
						ctx.getYushouCount());
                creditInvestigate(ctx);
//				creditReview(order, ctx);
				return true;
			} else {
				reject(order);
				log.info("风控执行 ordercode:{},createTime:{},风控失败", order.getOrdercode(), createTime);
				return false;
			}
		} catch (Exception e) {
			log.info("风控执行 ordercode:{} error", order.getOrdercode(), e);
			if (e.getCause() != null && e.getCause().getMessage() != null) {
				notifyReport(Lists.newArrayList("订单:" + order.getOrdercode() + ",异常:" + e.getCause().getMessage()));
			} else {
				notifyReport(Lists.newArrayList("订单:" + order.getOrdercode() + ",异常:" + e.getMessage()));
			}
		}
		return false;
	}

    /**
     * 包装用户信息 含征信相关
     */
    private UserInfo buildFullUserInfo(UserInfo userInfo, CreditFile creditFile) {
        CreditAuthInfo creditAuthInfo = new CreditAuthInfo();
        creditAuthInfo.setUid(userInfo.getUid());
        creditAuthInfo.setUserName(userInfo.getName());
        creditAuthInfo.setSex(userInfo.getSex());
        creditAuthInfo.setIdCard(userInfo.getId());
        creditAuthInfo.setIdLastdate(userInfo.getIdLastdate());
        creditAuthInfo.setPhone(userInfo.getPhone());
        creditAuthInfo.setIdCardFrontUrl(creditFile.getIdCardFrontUrl());
        creditAuthInfo.setIdCardBackUrl(creditFile.getIdCardBackUrl());
        creditAuthInfo.setPersonVerifyUrl(creditFile.getPersonVerifyUrl());
        creditAuthInfo.setCaAuthUrl(creditFile.getCaAuthUrl());
        creditAuthInfo.setGuaranteeApplyUrl(creditFile.getGuaranteeApplyUrl());
        creditAuthInfo.setAuthorizationStatus(AuthStatus.NOT_SUBMIT.getCode());

        CreditAuthInfo effectAuthInfo = creditService.getEffectAuthInfoByUid(userInfo.getUid());
        if (Objects.isNull(effectAuthInfo)) {
            userInfo.setCreditAuthInfo(creditAuthInfo);
            return userInfo;
        }

        creditAuthInfo.setId(effectAuthInfo.getId());
        creditAuthInfo.setSerialNumber(effectAuthInfo.getSerialNumber());
        creditAuthInfo.setAuthSubmitDatetime(effectAuthInfo.getAuthSubmitDatetime());
        creditAuthInfo.setAuthExpireDatetime(effectAuthInfo.getAuthExpireDatetime());
        creditAuthInfo.setAuthorizationStatus(effectAuthInfo.getAuthorizationStatus());
        creditAuthInfo.setCreditInfo(effectAuthInfo.getCreditInfo());
        if (AuthStatus.SUBMIT.getCode().equals(effectAuthInfo.getAuthorizationStatus())) {
            userInfo.setRiskNode(RiskNodes.RISK_ONE.getCode());
        }else if (AuthStatus.AUTH_SUCCESS.getCode().equals(effectAuthInfo.getAuthorizationStatus())
                || AuthStatus.AUTH_FAILED.getCode().equals(effectAuthInfo.getAuthorizationStatus())) {
            userInfo.setRiskNode(RiskNodes.RISK_TWO.getCode());
        }
        userInfo.setCreditAuthInfo(creditAuthInfo);
        return userInfo;
    }

    /*---------------------风控二阶段（征信）-------------------------*/

    public void execRiskTwo() {
        for (OrderInfo order : riskService.findRiskTwoOrders()) {
            String createTime = DateUtils.format(new Date(order.getCreatetime() * 1000), "yyyyMMdd");
            log.info("风控二阶段执行 orderCode:{},createTime:{}", order.getOrdercode(), createTime);
            execRiskTwoOrder(order);
            log.info("风控二阶段执行 结束 orderCode:{}", order.getOrdercode());
        }
    }

    public Boolean execRiskTwo(int oid) {
        return execRiskTwoOrder(riskService.findRiskOrder(oid));
    }

    private Boolean execRiskTwoOrder(OrderInfo order){
        String createTime = DateUtils.format(new Date(order.getCreatetime() * 1000), "yyyyMMdd");
        if (riskService.isInRiskTwo(order.getOrdercode())){
            log.info("风控二阶段 orderCode:{},createTime:{} 已在信审中", order.getOrdercode(), createTime);
            return true;
        }
        try {
            ApiContext ctx = this.initApiContextRiskTwo(order);
            if (ctx == null) {
                return false;
            }

            droolsService.execRiskTwo(ctx); // 执行征信相关规则

            if (ctx.getUserInfo().getIsB0013()){
                log.info("风控二阶段执行 C9005-该报告尚未生成,请稍后再试 orderCode : {}", order.getOrdercode());
                return false;
            }

            if (ctx.getRuleResult() != null && ctx.getRuleResult()) {
                log.info("风控二阶段执行 orderCode:{},createTime:{},风控二阶段成功,yushou期数:{}", order.getOrdercode(),
                        createTime, ctx.getYushouCount());
				creditReview(order, ctx);
                return true;
            } else {
                reject(order);
                log.info("风控二阶段执行 orderCode:{},createTime:{},风控失败", order.getOrdercode(), createTime);
                return false;
            }
        }catch (Exception e){
            log.info("风控二阶段执行 ordercode:{} error", order.getOrdercode(), e);
            if (e.getCause() != null && e.getCause().getMessage() != null) {
                log.info("订单:" + order.getOrdercode() + ",异常:" + e.getCause().getMessage());
                notifyReport(Lists.newArrayList("订单:" + order.getOrdercode() + ",异常:" + e.getCause().getMessage()));
            } else {
                log.info("订单:" + order.getOrdercode() + ",异常:" + e.getMessage());
                notifyReport(Lists.newArrayList("订单:" + order.getOrdercode() + ",异常:" + e.getMessage()));
            }
        }
        return true;
    }

    private ApiContext initApiContextRiskTwo(OrderInfo order) {
        CreditAuthInfo creditAuthInfo = creditService.getEffectAuthInfoByUid(order.getUid());
        if (creditAuthInfo == null) {
            log.info("风控二阶段 初始化上下文失败(effect authInfo is null) orderCode:{}", order.getOrdercode());
            return null;
        }
        RiskRuleResultInfo resultInfo = riskService.findLastRiskRuleResult(creditAuthInfo.getIdCard());
        if (resultInfo == null) {
            log.info("风控二阶段 初始化上下文失败(riskRuleResult is null) orderCode:{}", order.getOrdercode());
            return null;
        }

        UserInfo userInfo = new UserInfo();
        userInfo.setName(creditAuthInfo.getUserName());
        userInfo.setSex(creditAuthInfo.getSex());
        userInfo.setId(creditAuthInfo.getIdCard());
        userInfo.setIdLastdate(creditAuthInfo.getIdLastdate());
        userInfo.setPhone(creditAuthInfo.getPhone());
        userInfo.setRiskNode(RiskNodes.RISK_TWO.getCode());
        userInfo.setCreditAuthInfo(creditAuthInfo);

        ApiContext ctx = this.initApiContext(order, userInfo);
        ctx.setYushouCount(resultInfo.getYushouCount());

        return ctx;
    }

	private ApiContext initApiContext(OrderInfo order, UserInfo userInfo) {
		ApiContext ctx = new ApiContext();
		ctx.setOrder(order);
		ctx.setUserInfo(userInfo);

		ctx.setAuthDate("");
		ctx.setLastRefuseDate("");
		ctx.setLastRefuseDate("");
		ctx.setYushouCount(0);
		return ctx;
	}

    private void notifyReport(List<String> contents) {
        List<String> users = Lists.newArrayList();
        users.add("chenjunping-gbj");
        users.add("wangfeng-gbj");
        weChatService.sendMessage(WechatBotKeyEnum.ORDER, WechatNotificationType.BLACK, "风控执行异常", users, contents);
    }

	private void reject(OrderInfo order) {
		log.info("关闭订单 ordercode:{}", order.getOrdercode());
		orderOpService.reject(order.getId());
	}

    private void creditInvestigate(ApiContext ctx) {
        log.info("进入征信检测订单 ordercode:{}", ctx.getOrder().getOrdercode());
        orderOpService.creditInvestigate(ctx.getOrder().getId());
    }

	private void creditReview(OrderInfo order,ApiContext ctx) {
		log.info("信审授权订单 ordercode:{}", order.getOrdercode());
		orderOpService.creditReview(order.getId(),ctx.getYushouCount());
	}
}
